﻿using System;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using BBCode.Collections;
using BBCode.Nodes;
using BBCode.Tags;

namespace BBCode
{
    /// <summary>
    /// Parsing results.
    /// </summary>
    public class ParseResult
    {
        private NodeCollection _nodes;

        /// <summary>
        /// Gets or sets the nodes.
        /// </summary>
        /// <value>
        /// The nodes.
        /// </value>
        public NodeCollection Nodes
        {
            get { return _nodes; }
            set { _nodes = value; }
        }

        /// <summary>
        /// Gets or sets the text.
        /// </summary>
        /// <value>
        /// The text.
        /// </value>
        public string Text { get; set; }

        /// <summary>
        /// Prints the ouput specified should auto parse links.
        /// </summary>
        /// <param name="shouldAutoParseLinks">if set to <c>true</c> will attempt to automatically parse links.</param>
        /// <returns></returns>
        public string Print(bool shouldAutoParseLinks = true)
        {
            var stringBuilder = new StringBuilder(Text);

            //Go through the nodes, in the right order
            var orderedNodes = from n in _nodes
                                                     orderby n.Tag.Priority descending
                                                     select n;

            //Set the ID's of all the nodes
            foreach (var node in orderedNodes)
            {
                var firstIndex = stringBuilder.ToString().IndexOf(node.Text);
                stringBuilder.Replace(node.Text, node.ID, firstIndex, node.Text.Length);
            }

            //Auto parsing goes here!
            if (shouldAutoParseLinks)
            {
                var matches = Regex.AutoParseRegex.Matches(stringBuilder.ToString());

                foreach (Match m in matches)
                {
                    stringBuilder.Replace(m.Value, "<a href=\"" + m.Value + "\" rel=\"nofollow\">" + m.Value + "</a>");
                }
            }
            //End auto parsing

            //Replace the ID's with the right text
            foreach (var node in _nodes)
            {
                stringBuilder.Replace(node.ID, node.Print(shouldAutoParseLinks));
            }

            stringBuilder.Replace(Environment.NewLine, "<br/>");

            return stringBuilder.ToString();
        }

        /// <summary>
        /// Gets the first node in a collection of nodes of a specific tag.
        /// </summary>
        /// <param name="tag">The tag.</param>
        /// <param name="nodes">The nodes.</param>
        /// <returns></returns>
        private INode GetFirst(ITag tag, NodeCollection nodes)
        {
            foreach (INode node in nodes)
            {
                if (node.Tag.Name == tag.Name)
                {
                    return node;
                }
                var nestableNode = node as INestableNode;
                if (nestableNode == null || !nestableNode.HasChildren) continue;
                var result = GetFirst(tag, nestableNode.Children);
                if (result == null) continue;
                return result;
            }
            return null;
        }

        /// <summary>
        /// Gets the first node of a specific tag.
        /// </summary>
        /// <param name="tag">The tag.</param>
        /// <returns></returns>
        public INode GetFirst(ITag tag)
        {
            return GetFirst(tag, Nodes);
        }
    }
}